from flask_restful import Resource
from flask import current_app,request,g
from common.utils.sms_send import send_sms
import random,json
from common.utils.limiter import limiter as lmt
from flask_restful.reqparse import RequestParser  # 请求参数验证
from shopping.resource.user import constants
from flask_limiter.util import get_remote_address
from common.utils.shopping_redis import redis_client
from flask_restful.reqparse import RequestParser # 请求参数验证
from common.utils import parser
from common.models.user import User
from common.models import db
from common.utils.tokens_pyjwt import generate
from common.utils.decorators import login_required

# 我们定义的测试的资源类
class Shopping_User(Resource):
    '''
    在get函数上加上登陆的拦截
    '''
    method_decorators = {
        'get':[login_required],
        'post':[login_required]
    }

    def get(self):
        current_app.logger.info('我的测试日志')
        # 这里可能会用到User模型类
        return {'hello': '测试'}

# 调用短信验证码
class User_SMS(Resource):
    error_message = 'Too many requests.'
    decorators = [
    # 三个参数：参数1：限流的速率 参数2：key_func
    lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,
              key_func=lambda:request.args['phone'],
              error_message = error_message),
    # ip限流器
    lmt.limit(constants.LIMIT_SMS_CODE_BY_IP,
              key_func=get_remote_address,
              error_message=error_message)

    ]

    def get(self):
        phone = request.args.get('phone').strip()
        code = random.randint(1000,9999) # 4位
        text = "您的验证码是：{}。请不要把验证码泄露给其他人。".format(str(code))
        result = send_sms(text,phone) # 返回的是JSON字符串
        result = json.loads(result) # 把JSON变为字典
        # result 往里添加手机号
        result['phone'] = phone

        # 短信验证码发送成功后，还需把验证码存放到Redis数据库中，以便于下次验证，验证码时间为5分钟
        redis_client.setex('shopping:code:{}'.format(phone),constants.SMS_CODE_EXPIRES,code) # 参数1：key 参数2：时效

        return result


class AuthorizationCodeResource(Resource):
    '''
     提交手机号和验证码，开始验证
    '''
    def post(self):
        rp = RequestParser()
        rp.add_argument('phone',type=parser.mobile,required=True)
        rp.add_argument('code',type=parser.regex(r'^\d{4}$'),required=True)
        args = rp.parse_args()
        phone = args.phone
        code = args.code

        # 从Redis数据库得到之前保存的验证码
        key = 'shopping:code:{}'.format(phone)
        try:
            real_code = redis_client.get(key)
        except ConnectionError as e:
            current_app.logger.error(e)
            return {'message':'redis db connect error.'},400

        # 开始校验
        if not real_code or real_code.decode() != code:
            return {'message':'Invalid code.'},400

        return {'phone':phone,'msg':'code success.'}


class RegisterUserResource(Resource):
    '''
    填写账号信息，完成用户注册
    '''
    def post(self):
        rp = RequestParser()
        rp.add_argument('phone', type=parser.mobile, required=True)
        rp.add_argument('username',required=True)
        rp.add_argument('password',required=True)
        rp.add_argument('email',type=parser.email,required=True)
        args = rp.parse_args()
        username = args.username
        password = args.password
        phone = args.phone
        email = args.email

        # 验证用户名是否唯一：先从sql数据库中根据当前用户名查询
        u = User.query.filter(User.username == username).first()
        if u:
            # 用户名重复
            current_app.logger.info(f'{username}:用户名已经存在，请换一个')
            return {'message':'The username already exists.'},400
        # 把用户信息保存到数据库中
        u = User(phone=phone,username=username,pwd=password,email=email,status=0)
        db.session.add(u)
        db.session.commit()
        return {'msg':'ok'}

class UserLoginResource(Resource):
    '''
    登录
    '''
    def post(self):
        username = request.form.get('username')
        password = request.form.get('password')
        if not all([username,password]):
            return {'message':'数据不完整'},401

        user = User.query.filter(User.username==username).first()
        if user:
            # 拿用户名的密码进行校验
            if user.check_password(password):
                # 登陆成功之后的用户，id得到token，token返回前端
                token = generate(user.id)
                return { 'msg':'Login success','token':token,'username':username},200
        return {'message':'用户名或密码错误.'},400


class IsExistPhoneResource(Resource):
    '''
    判断手机号是否存在
    '''
    def post(self):
        phone = request.form.get('phone')
        user = User.query.filter(User.phone ==phone).first()
        if user: # 如果user存在,则表示手机号存在
            return {'isExist':True,'message':'手机号已注册！','code':201}
        return {'msg':'手机号未注册！'}


class UserLoginOutResource(Resource):
    '''
    退出登录
    '''
    def post(self):
        if g.user_id:
            g.user_id= None
        return {'msg':'退出登录'}